package com.cdck.safe.dete.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdck.safe.dete.model.bo.SeatBO;
import com.cdck.safe.dete.model.entity.Booking;
import com.cdck.safe.dete.model.entity.Seat;
import com.cdck.safe.dete.mapper.SeatMapper;
import com.cdck.safe.dete.model.query.BaseKeywordsQuery;
import com.cdck.safe.dete.model.query.SeatQuery;
import com.cdck.safe.dete.model.vo.SeatDataVo;
import com.cdck.safe.dete.model.vo.SeatStatusVO;
import com.cdck.safe.dete.service.BookingService;
import com.cdck.safe.dete.service.LaboratoryService;
import com.cdck.safe.dete.service.SeatService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import javax.annotation.Resource;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (Seat)表服务实现类
 *
 * @author wp
 * @since 2024-02-25 16:47:16
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class SeatServiceImpl extends ServiceImpl<SeatMapper, Seat> implements SeatService {

    private final LaboratoryService laboratoryService;

    private final BookingService bookingService;


    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public Seat getSeatFormData(Long id) {
        return this.getById(id);
    }

    /**
     * 分页查询
     * <p>
     * queryParams 筛选条件
     *
     * @return 查询结果
     */
    @Override
    public IPage<SeatDataVo> queryByPage(SeatQuery queryParams) {
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        String keywords = queryParams.getKeywords();
        Page<Seat> page = new Page<>(pageNum, pageSize);
        this.page(
                page,
                new LambdaQueryWrapper<Seat>()
                        .like(StrUtil.isNotBlank(keywords), Seat::getSeatNo, keywords)
                        .eq(!Objects.equals(queryParams.getLabId(), null), Seat::getLabId, queryParams.getLabId())
        );

        Page iPage = new Page<>(pageNum, pageSize);
        BeanUtils.copyProperties(page, iPage, "records");
        List<SeatDataVo> collect = page.getRecords().stream().map(item -> {
            SeatDataVo vo = new SeatDataVo();
            BeanUtils.copyProperties(item, vo);
            vo.setLabName(laboratoryService.getById(item.getLabId()).getName());
            return vo;
        }).collect(Collectors.toList());
        iPage.setRecords(collect);
        return iPage;
    }

    /**
     * 新增数据
     *
     * @param seat 实例对象
     * @return 实例对象
     */
    @Override
    public boolean saveSeat(Seat seat) {
        return this.save(seat);
    }

    /**
     * 修改数据
     *
     * @param seat 实例对象
     * @return 实例对象
     */
    @Override
    public boolean updateSeat(Long id, Seat seat) {
        return this.updateById(seat);
    }

    /**
     * 通过主键删除数据
     *
     * @param idsStr ids集合
     * @return 是否成功
     */
    @Override
    public boolean deleteSeats(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的数据为空");
        // 逻辑删除
        List<Long> ids = Arrays.stream(idsStr.split(","))
                .map(Long::parseLong).collect(Collectors.toList());
        return this.removeByIds(ids);
    }

    @Override
    public List<Seat> getSeatListByLabId(Long id) {
        return this.list(new LambdaQueryWrapper<Seat>().eq(Seat::getLabId, id));
    }

    @Override
    public List<SeatStatusVO> getSeatStatus(SeatBO seatBO) {

        LambdaQueryWrapper<Seat> seatQueryWrapper = new LambdaQueryWrapper<>();
        seatQueryWrapper.eq(Seat::getLabId, seatBO.getLabId());
        List<Seat> seatList = this.list(seatQueryWrapper);
        if (seatList != null && seatList.size() > 0) {
            List<SeatStatusVO> voList = seatList.stream().map(item -> {
                SeatStatusVO vo = new SeatStatusVO();
                BeanUtils.copyProperties(item, vo);
                //查找这个作座位的所有预约记录
                LambdaQueryWrapper<Booking> bookingWrapper = new LambdaQueryWrapper<>();
                bookingWrapper
                        .eq(Booking::getLabId, seatBO.getLabId())
                        .eq(Booking::getStatus, 2)
                        .eq(Booking::getSeatId, item.getId())
                        .gt(Booking::getBookEndTime, LocalDateTime.now());
                List<Booking> bookingList = bookingService.list(bookingWrapper);
                if (bookingList == null && bookingList.size() == 0) {
                    //没有预约记录，直接返回
                    return vo;
                }
                for (Booking booking : bookingList) {
                    //如果这个时间段，记录表里面有记录，且在使用范围，说明作为被占用
                    long bookingStartTime = booking.getBookStartTime().getTime();
                    long bookingEndTime = booking.getBookEndTime().getTime();
                    long seatStartTime = seatBO.getStartTime().getTime();
                    long seatEndTime = seatBO.getEndTime().getTime();

                    // 检查预订与座位时间范围是否有交叉,三种情况
                    if ((seatStartTime >= bookingStartTime && seatEndTime <= bookingEndTime)
                            || (seatStartTime <= bookingStartTime && seatEndTime >= bookingStartTime)
                            || (seatStartTime <= bookingEndTime && seatEndTime >= bookingEndTime)) {
                        vo.setStatus(1); // 设置座位状态为已预订
                    }
                }
                return vo;
            }).collect(Collectors.toList());

            return voList;
        }

        return new ArrayList<>();
    }

    public static void main(String[] args) {
        Date date = new Date();
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();

        System.out.println("Date: " + date);
        System.out.println("LocalDateTime: " + localDateTime);
    }
}
